import axios from 'axios'
import store from '@/store'
import storage from 'store'
import expirePlugin from 'store/plugins/expire'
import notification from 'ant-design-vue/es/notification'
import { VueAxios } from './axios'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { refreshToken } from '@/api/login'
storage.addPlugin(expirePlugin)
// 是否正在刷新的标志
window.isRefreshing = false
// 存储请求的数组
let cacheRequestArr = []

// 将所有的请求都push到数组中,其实数组是[function(token){}, function(token){},...]
function cacheRequestArrHandle (cb) {
  cacheRequestArr.push(cb)
}
// 数组中的请求得到新的token之后自执行，用新的token去重新发起请求
function afreshRequest (token) {
  cacheRequestArr.map(cb => cb(token))
  cacheRequestArr = []
}
// 判断token是否即将过期
function isTokenExpired () {
  const curTime = new Date().getTime()
  const getExpires = localStorage.getItem('expire_time')
  const expiresTime = Number(getExpires) - curTime
  if ((expiresTime >= 0 && expiresTime < 900000) || (expiresTime < 0 && Math.abs(expiresTime) <= 1200000)) {
    return true
  }
  return false
}

// 创建 axios 实例
const request = axios.create({
  // API 请求的默认前缀
  // baseURL: process.env.VUE_APP_API_BASE_URL,
  baseURL: process.env.NODE_ENV === 'development' ? '/api' : process.env.VUE_APP_API_BASE_URL,
  // timeout: 6000 // 请求超时时间
  timeout: 600000 // 请求超时时间
})

// 异常拦截处理器
const errorHandler = (error) => {
  console.log('异常拦截处理器' + error)
  if (error.response) {
    const data = error.response.data
    // 从 localstorage 获取 token
    const token = storage.get(ACCESS_TOKEN)

    if (error.response.status === 403) {
      notification.error({
        message: 'Forbidden',
        description: data.message
      })
    }
    if (error.response.status === 401 && !(data.result && data.result.isLogin)) {
      notification.error({
        message: 'Unauthorized',
        description: 'Authorization verification failed'
      })
      if (token) {
        store.dispatch('Logout').then(() => {
          setTimeout(() => {
            window.location.reload()
          }, 1500)
        })
      }
    }
  }
  return Promise.reject(error)
}

// 请求拦截
request.interceptors.request.use(config => {
  const token = storage.get(ACCESS_TOKEN)
  // 如果 token 存在
  // 让每个请求携带自定义 token 请根据实际情况自行修改
  if (token) {
    config.headers[ACCESS_TOKEN] = token
    // 判断token是否即将过期，且不是请求刷新token的接口
    if (isTokenExpired() && config.url !== '/login/refreshToken') {
      // 所有的请求来了，先判断是否正在刷新token，
      // 如果不是，将刷新token标志置为true并请求刷新token.
      // 如果是，则先将请求缓存到数组中
      // 等到刷新完token后再次重新请求之前缓存的请求接口即可
      if (!window.isRefreshing) {
        // 标志改为true，表示正在刷新
        window.isRefreshing = true
        localStorage.setItem('expire_time', '')
        refreshToken().then(res => {
          if (res.code == 200) {
            const getToken = res.data
            // 将刷新的token替代老的token
            config.headers[ACCESS_TOKEN] = getToken
            // 刷新token完成后重新请求之前的请求
            afreshRequest(getToken)
            // 过期时间为1小时
            const expireTime = new Date().getTime() + 1000 * 60 * 60 * 1
            storage.set(ACCESS_TOKEN, getToken, expireTime)
            localStorage.setItem('expire_time', expireTime)
            // 更新 store里的值
            store.commit('SET_TOKEN', getToken)
          } else {
            notification.error({
              message: res.message,
              description: 'error'
            })
            store.dispatch('Logout').then(() => {
              setTimeout(() => {
                window.location.reload()
              }, 1500)
            })
          }
        }).catch(err => {
          store.dispatch('Logout').then(() => {
            setTimeout(() => {
              window.location.reload()
            }, 1500)
          })
        }).finally(() => {
          window.isRefreshing = false
        })
        // 下面这段代码一定要写，不然第一个请求的接口带过去的token还是原来的，要将第一个请求也缓存起来
        const retry = new Promise((resolve) => {
          cacheRequestArrHandle((token) => {
            config.headers[ACCESS_TOKEN] = token // token为刷新完成后传入的token
            // 将请求挂起
            resolve(config)
          })
        })
        return retry
      } else {
        const retry = new Promise((resolve) => {
          cacheRequestArrHandle((token) => {
            config.headers[ACCESS_TOKEN] = token // token为刷新完成后传入的token
            // 将请求挂起
            resolve(config)
          })
        })
        return retry
      }
    } else {
      return config
    }
  }
  return config
}, errorHandler)

// response interceptor
request.interceptors.response.use((response) => {
  if (response.data.code == 222) {
    store.dispatch('Logout').then(() => {
      setTimeout(() => {
        window.location.reload()
      }, 1500)
    })
    return
  }
  return response.data
}, errorHandler)

const installer = {
  vm: {},
  install (Vue) {
    Vue.use(VueAxios, request)
  }
}

export default request

export {
  installer as VueAxios,
  request as axios
}
